package com.dl698.asn1.axdr;

import com.dl698.util.ReverseByteArrayInputStream;
import com.dl698.util.ReverseByteArrayOutputStream;

import java.io.IOException;

/**
 * AXDR可选类型类
 * 实现可选类型的编解码功能
 * 
 * @author wind
 * @version 1.1.1
 */
public class AxdrOptional<T extends AxdrType> {

    private T value = null;
    private boolean usage = false;

    /**
     * 构造函数
     * 
     * @param value 值
     * @param usage 使用标志
     */
    public AxdrOptional(T value, boolean usage) {
        if (value == null) {
            throw new RuntimeException("Value cannot be null");
        }
        this.value = value;
        this.usage = usage;
    }

    /**
     * 解码
     * 
     * @param input 输入流
     * @return 解码长度
     * @throws IOException IO异常
     */
    public int decode(ReverseByteArrayInputStream input) throws IOException {
        int codeLength = 0;
        AxdrBoolean axdrUsage = new AxdrBoolean();
        codeLength += axdrUsage.decode(input);
        this.usage = axdrUsage.getVal();
        if (this.usage) {
            codeLength += this.value.decode(input);
        }
        return codeLength;
    }

    /**
     * 编码
     * 
     * @param output 输出流
     * @return 编码长度
     * @throws IOException IO异常
     */
    public int encode(ReverseByteArrayOutputStream output) throws IOException {
        int codeLength = 0;
        if (this.usage) {
            if (this.value != null) {
                codeLength += this.value.encode(output);
            } else {
                throw new RuntimeException("value is null");
            }
        }
        AxdrBoolean usageBool = new AxdrBoolean();
        usageBool.setVal(this.usage);
        codeLength += usageBool.encode(output);
        return codeLength;
    }

    /**
     * 设置使用标志
     * 
     * @param use 使用标志
     */
    public void setUsed(boolean use) {
        this.usage = use;
    }

    /**
     * 检查是否使用
     * 
     * @return 使用标志
     */
    public boolean isUsed() {
        return this.usage;
    }

    /**
     * 获取值
     * 
     * @return 值
     */
    public T getValue() {
        if (this.value != null) {
            return this.value;
        } else {
            throw new RuntimeException("value is null");
        }
    }

    /**
     * 设置值
     * 
     * @param value 值
     */
    public void setValue(T value) {
        this.usage = this.value != null;
        if (this.value != null) {
            this.value = value;
        }
    }

    @Override
    public String toString() {
        if (this.usage) {
            if (this.value != null) {
                return this.value.toString();
            } else {
                throw new RuntimeException("value is null");
            }
        } else {
            return "not set";
        }
    }
}